package udp

import (
	"io"
	"math"
	"net"

	"gitee.com/hasika/common-server/conn/impl_base"
	"gitee.com/hasika/common-server/conn/inet"
)

type ServerConnection struct {
	*impl_base.Connection
	remoteAddress *net.UDPAddr
	ls            *Listener
}

func (t *ServerConnection) GetRemote() net.Addr {
	return t.remoteAddress
}

func (t *ServerConnection) InitFd() {

}

func (t *ServerConnection) Read(p []byte) (n int, err error) {
	defer func() {
		t.RecordRead(n)
	}()
	n, err = t.ReadCtx.Buffer().Read(p)
	if err == io.EOF {
		return n, nil
	}
	return n, err
}

func (t *ServerConnection) CloseConn() error {
	t.ls.connectionMap.Delete(t.remoteAddress.String())
	return nil
}

func NewServerConnection(remoteAddress *net.UDPAddr, ls *Listener) *ServerConnection {
	uc := &ServerConnection{remoteAddress: remoteAddress, ls: ls, Connection: impl_base.NewBaseConnection()}
	return uc
}

func (t *ServerConnection) GetConnectionType() inet.ConnectionType {
	return inet.Udp
}

func (t *ServerConnection) LowerWrite(data []byte) error {
	start := 0
	maxLen := len(data)
	for {
		currentWriteLen := int(math.Min(inet.BufferMaxLen, float64(maxLen-start)))
		writeLen, writeErr := t.ls.listenConn.WriteToUDP(data[start:start+currentWriteLen], t.remoteAddress)
		if writeErr != nil {
			inet.Log.Warnf("write error %+v", writeErr)
			return writeErr
		}
		start += writeLen
		if start >= maxLen {
			break
		}
	}
	t.RecordWrite(maxLen)
	return nil
}
